#include "binance.h"
#include "str_utils.h"

BinanceClient::BinanceClient(const std::string& config_path,
                             MARKETStruct* marketShmPtr,
                             boost::asio::io_context& ioc,
                             boost::asio::ssl::context& ssl_ctx)
    : marketShmPtr_(marketShmPtr) {
    YAML::Node yaml = YAML::LoadFile(config_path);
    config_path_ = config_path;
    const auto& binance = yaml["binance"];
    ws_host_ = binance["ws_host"].as<std::string>();
    ws_port_ = binance["ws_port"].as<std::string>();
    https_host_ = binance["https_host"].as<std::string>();
    https_port_ = binance["https_port"].as<std::string>();
    orderbook_depth_ = binance["orderbook_depth"].as<int>(5);

    mdConn_ = std::make_shared<WSConnection>(ioc, ssl_ctx);
    // tdConn_ = std::make_shared<WSConnection>(ioc, ssl_ctx);

    httpsConnPool_ = std::make_shared<HttpsConnectionPool>(ioc, ssl_ctx, https_host_, https_port_);

    mdConn_->setConnectHandler([this]() {
        std::cout << "行情WS连接成功" << std::endl;
        subscribeMarkets();
        initOrderBooks();
    });
    mdConn_->setMessageHandler([this](const std::string& msg) { handleMarketMessage(msg); });
    mdConn_->setErrorHandler([](const std::string& err) {
        std::cerr << "WS Error: " << err << std::endl;
    });
}

BinanceClient::~BinanceClient() {
    try {
        printOrderBooks();
        std::cout << "✅ BinanceClient 析构完成，资源已释放。" << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "❌ BinanceClient 析构异常: " << e.what() << std::endl;
    }
}

void BinanceClient::subscribeMarkets() {
    YAML::Node yaml = YAML::LoadFile(config_path_);
    const YAML::Node& binance = yaml["binance"];

    if (!binance["subscribe_markets"]) {
        throw std::runtime_error("配置文件中缺少 subscribe_markets");
    }

    int market_id = 1; // 订阅请求ID，可以根据需要自增
    for (auto& sym : binance["subscribe_markets"]) {
        std::string symbol = sym.as<std::string>();

        // 转成小写
        std::transform(symbol.begin(), symbol.end(), symbol.begin(),
                       [](unsigned char c){ return std::tolower(c); });

        // 拼接成订阅请求
        std::string subMarket = R"({"method": "SUBSCRIBE","params":[")" 
                                + symbol + "usdt@depth" + R"("],"id":)" 
                                + std::to_string(market_id) + "}";

        mdConn_->send(subMarket);
        std::cout << "📡 已订阅市场: " << symbol << std::endl;

        market_id++; // 每个请求ID不同
    }
}

void BinanceClient::initOrderBooks() {
    try {
        YAML::Node yaml = YAML::LoadFile(config_path_);
        const YAML::Node& binance = yaml["binance"];

        if (!binance|| !binance["subscribe_markets"]) {
            throw std::runtime_error("配置文件中缺少 binance.subscribe_markets");
        }

        for (auto& symNode : binance["subscribe_markets"]) {
            std::string base = symNode.as<std::string>();
            toUpper(base);
            getCurrentOrderBook(base);
        }
    } catch (const std::exception& e) {
        std::cerr << "BinanceClient::initOrderBooks 异常: " << e.what() << std::endl;
    }
}

void BinanceClient::getCurrentOrderBook(const std::string& baseSymbol) {
    std::string symbol = baseSymbol + "USDT"; // 拼接成 BTCUSDT、ETHUSDT 等

    std::ostringstream target;
    target << "/fapi/v1/depth?symbol=" << symbol << "&limit=1000";

    std::cout << "📡 [BinanceClient] 初始化请求订单簿：" << symbol << std::endl;

    httpsConnPool_->asyncSendRequest(
        "GET",
        target.str(),
        "", // body
        {}, // headers
        [this, symbol](const boost::system::error_code& ec, const std::string& body) {
            if (ec) {
                std::cerr << "BinanceClient::initOrderBooks 获取 " << symbol
                          << " 深度失败: " << ec.message() << std::endl;
                return;
            }

            rapidjson::Document doc;
            doc.Parse(body.c_str());
            if (doc.HasParseError()) {
                std::cerr << "解析 JSON 失败 (" << symbol << "): " << std::endl;
                return;
            }

            if (!doc.HasMember("bids") || !doc.HasMember("asks")) {
                std::cerr << "返回数据中缺少 bids/asks 字段 (" << symbol << ")" << std::endl;
                return;
            }

            BinanceOrderBook ob;
            ob.lastUpdateId = doc["lastUpdateId"].GetUint64();

            const auto& bids = doc["bids"];
            for (auto& bidItem : bids.GetArray()) {
                double price = stringToUint64(bidItem[0].GetString());
                double qty = std::stod(bidItem[1].GetString());
                ob.bids[price] = qty;
            }

            const auto& asks = doc["asks"];
            for (auto& askItem : asks.GetArray()) {
                double price = stringToUint64(askItem[0].GetString());
                double qty = std::stod(askItem[1].GetString());
                ob.asks[price] = qty;
            }

            // 存入本地 orderBooks_
            orderBooks_[symbol] = std::move(ob);

            std::cout << "✅ 已加载 " << symbol
                      << " 深度信息，共 " << orderBooks_[symbol].bids.size()
                      << " bids, " << orderBooks_[symbol].asks.size()
                      << " asks" << std::endl;

            // 写入前5档到共享内存
            writeTopNLevelsToShm(symbol, orderBooks_[symbol]);
        });
}

void BinanceClient::updateOrderBook() {
    for (auto& [symbol, updatesList] : orderBookUpdates_) {
        auto it = orderBooks_.find(symbol);
        if (it == orderBooks_.end()) continue;

        BinanceOrderBook& book = it->second;

        while (!updatesList.empty()) {
            const BinanceOrderBookUpdate& update = updatesList.front();

            // 检查更新的连续性
            if (update.u < book.lastUpdateId || update.U > book.lastUpdateId) {
                // 已处理过的更新，直接丢弃
                updatesList.pop_front();
                continue;
            }

            // 应用买盘更新并逐个检查是否影响前N档
            if (!update.bids.empty()) {
                for (const auto& [price, qty] : update.bids) {
                    if (qty == 0) {
                        book.bids.erase(price);
                    } else {
                        book.bids[price] = qty;
                    }
                    // 对单条更新进行检查并写入共享内存
                    checkAndWriteUpdateToShm(symbol, book, price, qty, OrderSideEnum::BID);
                }
            }

            // 应用卖盘更新并逐个检查是否影响前N档
            if (!update.asks.empty()) {
                for (const auto& [price, qty] : update.asks) {
                    if (qty == 0) {
                        book.asks.erase(price);
                    } else {
                        book.asks[price] = qty;
                    }
                    // 对单条更新进行检查并写入共享内存
                    checkAndWriteUpdateToShm(symbol, book, price, qty, OrderSideEnum::ASK);
                }
            }

            // 移除已处理的更新
            updatesList.pop_front();
        }
    }
}

void BinanceClient::run() {
    mdConn_->connect(ws_host_, ws_port_, "/ws");
}

void BinanceClient::handleMarketMessage(const std::string& msg) {
    rapidjson::Document doc;
    if (doc.Parse(msg.c_str()).HasParseError()) {
        std::cerr << "JSON 解析失败: " << msg << std::endl;
        return;
    }

    if (doc.HasMember("result") && doc.HasMember("id")) {
        if (doc["result"].IsNull()) {
            // 订阅成功消息，直接跳过
            std::cout << "✅ 订阅成功确认 (id=" << doc["id"].GetInt() << ")" << std::endl;
            return;
        } else {
            // result 不为 null，代表订阅失败或异常
            std::cerr << "订阅失败或异常响应: " << msg << std::endl;
            return;
        }
    }

    if (!doc.HasMember("s") || !doc.HasMember("U") || !doc.HasMember("u") || !doc.HasMember("pu")) {
        std::cerr << "缺少必要字段: " << msg << std::endl;
        return;
    }

    BinanceOrderBookUpdate update;
    update.U  = doc["U"].GetInt64();
    update.u  = doc["u"].GetInt64();
    update.pu = doc["pu"].GetInt64();
    const std::string symbol = doc["s"].GetString();
    update.symbol = symbol;

    //如果该pu不等于上一个update的u，说明数据不连续，直接丢弃
    if(symbol_u_.find(symbol) != symbol_u_.end()) {
        long long int last_u = symbol_u_[symbol];
        if (update.pu != last_u) {
            //删除当前的orderbook
            orderBooks_.erase(symbol);
            getCurrentOrderBook(symbol.substr(0, symbol.size() - 4)); // 去掉USDT后缀
            std::cout << last_u << " " << update.pu << std::endl;
            std::cout << "数据不连续，已重新请求订单簿: " << symbol << std::endl;
        }
    }
    symbol_u_[symbol] = update.u;
    // 解析 bids
    if (doc.HasMember("b") && doc["b"].IsArray()) {
            const auto& bids = doc["b"];
        for (auto& item : bids.GetArray()) {
            if (item.IsArray() && item.Size() >= 2) {
                uint64_t price  = stringToUint64(item[0].GetString());
                double volume = std::stod(item[1].GetString());
                update.bids.emplace_back(price, volume);
            }
        }
    }

    // 解析 asks
    if (doc.HasMember("a") && doc["a"].IsArray()) {
        const auto& asks = doc["a"];
        for (auto& item : asks.GetArray()) {
            if (item.IsArray() && item.Size() >= 2) {
                uint64_t price  = stringToUint64(item[0].GetString());
                double volume = std::stod(item[1].GetString());
                update.asks.emplace_back(price, volume);
            }
        }
    }

    // 插入 orderBookUpdates_
    auto& updatesList = orderBookUpdates_[symbol];
    updatesList.push_back(std::move(update));

    updateOrderBook();

    std::cout << "接收到深度更新: " << symbol << std::endl;
}

void BinanceClient::writeTopNLevelsToShm(const std::string& symbol, const BinanceOrderBook& book) {
    std::string baseSymbol = symbol.substr(0, symbol.size() - 4); // 去掉USDT后缀
    // 获取 market_id
    uint32_t market_id;
    auto it = SymbolEnumMap.find(baseSymbol);
    if (it != SymbolEnumMap.end()) {
        market_id = static_cast<uint32_t>(it->second);
    } else {
        std::cout << "Symbol not found!" << std::endl;
    }
    
    // 写入前 n 档卖单
    int i = 0;
    for (auto it = book.asks.begin();
         it != book.asks.end() && i < orderbook_depth_; ++it, ++i) {
        PriceLevelStruct pls{};
        pls.exchange = static_cast<uint8_t>(ExchangeEnum::BINANCE);
        pls.market_id = market_id;
        pls.pl.price = it->first;
        pls.pl.size = it->second;
        pls.order_side = OrderSideEnum::ASK;
        marketShmPtr_->priceLevelShm.push(pls);
    }

    // 写入前 n 档买单
    i = 0;
    for (auto it = book.bids.begin(); it != book.bids.end() && i < orderbook_depth_; ++it, ++i) {
        PriceLevelStruct pls{};
        pls.exchange = static_cast<uint8_t>(ExchangeEnum::BINANCE);
        pls.market_id = market_id;
        pls.pl.price = it->first;
        pls.pl.size = it->second;
        pls.order_side = OrderSideEnum::BID;
        marketShmPtr_->priceLevelShm.push(pls);
    }
}

void BinanceClient::checkAndWriteUpdateToShm(const std::string& symbol,
                                             const BinanceOrderBook& book,
                                             uint64_t price,
                                             double size,
                                             OrderSideEnum side) {
    std::string baseSymbol = symbol.substr(0, symbol.size() - 4); // 去掉USDT后缀
    // 获取 market_id
    uint32_t market_id;
    auto it = SymbolEnumMap.find(baseSymbol);
    if (it != SymbolEnumMap.end()) {
        market_id = static_cast<uint32_t>(it->second);
    } else {
        std::cout << "Symbol not found!" << std::endl;
    }
    
    if (side == OrderSideEnum::ASK) {
        // 获取当前第 N 档卖价
        uint64_t sellBoundary = 0;
        int i = 0;
        for (auto it2 = book.asks.begin(); it2 != book.asks.end() && i < orderbook_depth_; ++it2, ++i)
            sellBoundary = it2->first;

        // 检查单条更新是否影响前N档
        if (price <= sellBoundary) {
            PriceLevelStruct pls{};
            pls.exchange = static_cast<uint8_t>(ExchangeEnum::BINANCE);
            pls.market_id = market_id;
            pls.pl.price = price;
            pls.pl.size = size;
            pls.order_side = OrderSideEnum::ASK;
            marketShmPtr_->priceLevelShm.push(pls);

            // 额外处理 size==0：写入更新后的第 N 档
            if (size == 0 && price <= sellBoundary) {
                i = 0;
                for (auto it = book.asks.begin(); it != book.asks.end(); ++it, ++i) {
                    if (i == orderbook_depth_ - 1) {
                        PriceLevelStruct pls2{};
                        pls2.exchange = static_cast<uint8_t>(ExchangeEnum::BINANCE);
                        pls2.market_id = market_id;
                        pls2.pl.price = it->first;
                        pls2.pl.size = it->second;
                        pls2.order_side = OrderSideEnum::ASK;
                        marketShmPtr_->priceLevelShm.push(pls2);
                        break;
                    }
                }
            }
        }
    } else { // BID
        // 获取当前第 N 档买价
        long long buyBoundary = 0;
        int i = 0;
        for (auto it2 = book.bids.begin(); it2 != book.bids.end() && i < orderbook_depth_; ++it2, ++i)
            buyBoundary = it2->first;

        // 检查单条更新是否影响前N档
        if (price >= buyBoundary) {
            PriceLevelStruct pls{};
            pls.exchange = static_cast<uint8_t>(ExchangeEnum::BINANCE);
            pls.market_id = market_id;
            pls.pl.price = price;
            pls.pl.size = size;
            pls.order_side = OrderSideEnum::BID;
            marketShmPtr_->priceLevelShm.push(pls);

            // 额外处理 size==0：写入更新后的第 N 档
            if (size == 0 && price >= buyBoundary) {
                i = 0;
                for (auto it = book.bids.begin(); it != book.bids.end() && i < orderbook_depth_; ++it, ++i) {
                    if (i == orderbook_depth_ - 1) {
                        PriceLevelStruct pls2{};
                        pls2.exchange = static_cast<uint8_t>(ExchangeEnum::BINANCE);
                        pls2.market_id = market_id;
                        pls2.pl.price = it->first;
                        pls2.pl.size = it->second;
                        pls2.order_side = OrderSideEnum::BID;
                        marketShmPtr_->priceLevelShm.push(pls2);
                        break;
                    }
                }
            }
        }
    }
}

void BinanceClient::printOrderBooks() const {
    std::cout << "\n📊 binance 当前 OrderBook 状态：" << std::endl;
    for (const auto& [symbol, book] : orderBooks_) {
        std::cout << "\n--- " << symbol << " ---\n";
        int i = 0;
        std::cout << "ASKS:\n";
        for (auto it = book.asks.begin(); it != book.asks.end() && i < orderbook_depth_; ++it, ++i)
            std::cout << "  " << i << ": price=" << it->first << " size=" << it->second << "\n";
        i = 0;
        std::cout << "BIDS:\n";
        for (auto it = book.bids.begin(); it != book.bids.end() && i < orderbook_depth_; ++it, ++i)
            std::cout << "  " << i << ": price=" << it->first << " size=" << it->second << "\n";
    }
}